#pragma once

#include <string>
#include <type_traits>
#include <unordered_set>


#ifndef OMIT_MESHATTR_OUTPUT_IDXTYPE
#define OMIT_MESHATTR_OUTPUT_IDXTYPE int const*
#endif

#ifndef OMIT_MESHATTR_OUTPUT_NUMOPS
#define OMIT_MESHATTR_OUTPUT_NUMOPS std::unordered_set<OMIT_MESHATTR_OUTPUT_IDXTYPE>
#endif

#define OMIT_MESHATTR_OUTPUT_OPTION_ByType(...)		\
OMIT_NAMESPACE::detail::_MeshAttr_OutputOPs_ByType<__VA_ARGS__>()

#define OMIT_MESHATTR_OUTPUT_OPTION_ByUUID(...)		\
OMIT_NAMESPACE::detail::_MeshAttr_OutputOPs_ByUUID(__VA_ARGS__)

namespace OMIT_NAMESPACE
{
	namespace detail
	{
		template <typename>
		struct type_hash
		{
			static constexpr int		i{ };
			static constexpr int const* value{ &i };
		};

		template <typename T>
		static constexpr auto type_hash_v = type_hash<T>::value;
	}
}

#define OMIT_MESHATTR_DEFINE_ATTR(className, memberName, attrName, ...)				\
struct _MeshAttr_##className : public detail::_MeshAttr_Base<_MeshAttr_##className>	\
{																					\
	using value_type = __VA_ARGS__;													\
	constexpr static OMIT_MESHATTR_OUTPUT_IDXTYPE UUID()							\
	{																				\
		return OMIT_NAMESPACE::detail::type_hash_v<_MeshAttr_##className>;					\
	}																				\
	static std::string Name() { return #attrName; }									\
	value_type _##memberName{};														\
	value_type Value() const { return _##memberName; }								\
};																					\
using Attr_##className = _MeshAttr_##className

